#include <iostream>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <ctime>

#include "log.hpp"

using namespace std;

Log log;

void handler(int signol)
{
    cout << "father process catch: " << signol << endl;
    // 采用非阻塞等待，此时会将僵尸状态子进程全部回收
    // 即便同时多个子进程发送信号给父进程，等到waitpid完毕后，已经不会有僵尸进程
    // 此时的pending的17号信号可能为1，那就再执行一次信号捕捉，只是没有回收到子进程，直接退出函数，进入内核态进行相关处理
    sleep(1);
    sigset_t sigfind;
    sigset_t oset;
    sigemptyset(&sigfind);//未决信号集
    sigemptyset(&oset);//阻塞信号集
    //读取捕捉后的未决信号集
    sigpending(&sigfind);//获取到目前进程的未决信号集
    while (waitpid(-1, nullptr, WNOHANG) > 0)
    {
        //打印未决信号集
        cout << "当前的未决信号集";
        for(int i = 31; i > 0; i--)
        {
            cout << sigismember(&sigfind, i);
        }
        cout << endl;
        //打印阻塞信号集
        cout << "当前的阻塞信号集";
        sigprocmask(SIG_BLOCK, nullptr, &oset);//获取到目前进程的阻塞信号集
        for(int i = 31; i > 0; i--)
        {
            cout << sigismember(&oset, i);
        }
        cout << endl;
        sleep(3);
        cout << "father catch child!!!"<< endl << endl;;
    }
}

int main()
{
    srand(time(nullptr));

    // 针对17号信号进行自定义动作
    signal(SIGCHLD, handler);

    log.enable(ClassFile);
    log(Info, "success to catch my handler");

    pid_t fatherpid = getpid();
    int i = 0;
    cout << i << endl;
    // cout << "now father not ready make child" << endl;
    while (i < 5)
    {
        if (getpid() == fatherpid) // 只有父进程才能调用fork
        {
            sleep(1);
            pid_t id = fork();
            if (id == 0)
            {
                // Child
                cout << "Childpid: " << getpid() << endl;
                while (true)
                {
                    sleep(i);
                    exit(1);
                }
            }
            i++;
        }
    }

    // father
    cout << "father sleep now" << endl;
    while (true)
    {
        sleep(10);
        cout << "father pid is " << getpid() << endl;
    }
    return 0;
}